#include "nstar_m26_dev.h"
#include "nstar_m26_api.h"

//#include "nstar_at_ata.h"
//#include "nstar_at_sms.h"

//#include "nstar_at_net.h"

#define MIN_INVALILD_SQ 12

extern int  nstar_at_hadware_init(void);
extern int  nstar_at_hadware_close(void);

#define Timer_Expired_Errcnt()		M26Timer_Expired(dev->private[TIMER_Errcnt], api_env.TIMER_Errcnt)
#define	Timer_Update_Errcnt()		M26Timer_Update(&dev->private[TIMER_Errcnt])

#define Timer_Expired_Check_Sq()	M26Timer_Expired(dev->private[TIMER_Check_Sq], api_env.TIMER_Check_Sq)
#define	Timer_Update_Check_Sq()		M26Timer_Update(&dev->private[TIMER_Check_Sq])

M26_DEV M26_DEV1;
static M26_DEV *dev= &M26_DEV1;
static struct m26_para api_env;
static int env_init_step= 1;


void run_PPPD_srcipt(void)
{
    const char *CMD_STR =  "udhcpc -fnq -t 1 -i usb0 -s /usr/share/udhcpc/4g.script";
	int ret,wcnt=3;
	do {
        ret= system(CMD_STR);
        printf("pppd start run return %d, wcnt %d\n", ret, wcnt);
    }while(0 != ret && wcnt--);
}





static void modify_step(unsigned char step)
{
	const char *step_str[]={
		"PWR_OFF",
		"PWR_ON", 			
		"CFG_TOP",			
		"CHECK_SIGNAL",	
		"CHECK_CPIN",		
		"CHECK_QNS",
		"CFG_BOTTOM",
		"INIT_OK",		
		"GRMS_GETTIME",	
	  	"GRMS_CONNECT",	
	  	"GRMS_ESTABLISHED",	
	  	"STPE_MAX",
	};
	dev->step= step;
	printf("4g step: [#%d]%s\n", step, step_str[step]);
}


static void env_init(void)
{
	api_env.ATA_RingCnt= 3;
	api_env.TIMER_Errcnt= 60;
	api_env.TIMER_Check_Sq= 10;
	Timer_Update_Errcnt();
	Timer_Update_Check_Sq();
	//modify_step(env_init_step);	/*对于已经开机后，调试程序时候，节约时间*/
}

void M26_do_reboot_module(void)
{
	printf("fatal err: 4g module reinit now\n");
	//nstar_at_hadware_close();
	modify_step(M26_PWR_OFF);
}

static void get_csq(void)
{
#define SQ_LOG_VAL 4	//触发日志的变化差值
	static unsigned char last_sq=0;
	unsigned char data;
	int off;
	char *p1;
	if(dev->cmd("AT+CSQ","CSQ"))
	{
		p1=strstr((const char*)(dev->rbuf),",");
		if(p1!=NULL){
			data= atoi(p1-2);
			if(data==99)	//99对应信号质量未知或不可测
				data=0;
			dev->sq= data;
			off= data- last_sq;
			if(off > SQ_LOG_VAL || off < -SQ_LOG_VAL){
				last_sq= data;
				m26_dbg("4g module signal quality: %d\n", last_sq);
			}		
		}
	}
}


static unsigned char module_cfg_top(void)
{
	
	if(!dev->cmd("ATE0","OK") ){/*关回显*/
		m26_dbg("err: ATE0\n");
		return 0;
	}

//	if(!dev->cmd("AT+IPR=115200","OK") ){/*固定波特率*/
//		m26_dbg("err: IPR\n");
//		return 0;
//	}
	return 1;
}
static unsigned char module_cfg_bottom(void)
{
#if 0
	char buf[20];
	sprintf(buf, "AT+CLVL=%d", 99);	/*音量*/
	if(!dev->cmd(buf,"OK")){	
		m26_dbg("err: CLVL\n");
		return 0;
	}
#endif

#ifdef M26_SMS_ENABLE
	if(!dev->cmd("AT+CMGF=1","OK")){// 1.设置短信文本模式	
		m26_dbg("err: CMGF\n");
		return 0;
	}
	
	if(!dev->cmd("AT+CSDH=1","OK")){// 2.设置短信信息头部显示编码方式等内容	
		m26_dbg("err: CSDH\n");
		return 0;
	}

	if(!dev->cmd("AT+CPMS=\"SM\",\"SM\",\"SM\"","OK")){	// 3.短信收件箱位置
		m26_dbg("err: CPMS\n");
		return 0;
	}
	
	if(!dev->cmd("AT+QAUDCH=2","OK")){	// 打开声音通道：0主通道（默认值）1    耳机通道 2双
		m26_dbg("err: QAUDCH\n");
		return 0;
	}
#endif
/*4G*/
    if(!dev->cmd("AT+QCFG=\"usbnet\",3","OK")){	// 打开声音通道：0主通道（默认值）1    耳机通道 2双
		m26_dbg("err: QCFG 3\n");
		return 0;
	}
    
    if(!dev->cmd("at+qnetdevctl=1,1,1","OK")){	// 打开声音通道：0主通道（默认值）1    耳机通道 2双
		m26_dbg("err: qnetdevctl\n");
		return 0;
	}
    
	return 1;
}


static void rec_hadware_status(unsigned char sta)
{
	dev->init_sta= sta;
	dev->last_err= dev->step;
}

static void timer_handle(void)
{
	static unsigned char oldstep=0;
	static unsigned char init_failed=0;
	
	if(oldstep!= dev->step)
		Timer_Update_Errcnt();
	oldstep = dev->step;
	if(Timer_Expired_Errcnt()){	
		if(init_failed < 5)
			init_failed++;
		else{
			init_failed= 0; 
			rec_hadware_status(M26_HARDWARE_ERR);
			m26_dbg("m26 init failed: %d\r\n", dev->step);
		}
		M26_do_reboot_module();
        Timer_Update_Errcnt();
	}
}


void M26_comm_Init(void)
{
	static unsigned char check_module_cnt;
	check_module_cnt=0;
	env_init();

	while(1)
	{
		switch(dev->step)
		{
			case M26_PWR_OFF:
				dev->pwrctl();
				if(dev->init_sta != M26_HARDWARE_ERR) {
					delay_s(10);
				}
				else
					delay_s(20*60);/*hadware err flag on, waiting for a longer time*/
				modify_step(M26_PWR_ON);
				check_module_cnt= 0;
				break;
			case M26_PWR_ON:
				if(nstar_at_hadware_init() == 0){
                    m26_dbg("usart fd open ok\r\n");
                    if(1 == dev->cmd("AT","OK")){
					    modify_step(M26_CFG_TOP);
                        break;
				    }
				}else {
                    m26_dbg("usart fd open err\r\n");    
                }
                
				 if(check_module_cnt > 5){
                    m26_dbg("waiting at respon faild\r\n");
					modify_step(M26_PWR_OFF);
				}
				else{
                    m26_dbg("waiting at respon %d\r\n", check_module_cnt);
					check_module_cnt++;
					delay_s(2);
				}
				break;
			case M26_CFG_TOP:	
                check_module_cnt= 0;
				if(1 == module_cfg_top())
					modify_step(M26_CHECK_SIGNAL);
				else
					delay_s(2);
				break;
		
			case M26_CHECK_SIGNAL:		
				get_csq();
				if( dev->sq > MIN_INVALILD_SQ && dev->sq <= 32)
					modify_step(M26_CHECK_CPIN);
				else
					delay_s(2);
				break;
			case M26_CHECK_CPIN:	
				if(dev->cmd("AT+CPIN?","+CPIN: READY"))		//检查SIM卡
					modify_step(M26_CHECK_QNS);
				else
					delay_s(2);
				break;
			case M26_CHECK_QNS:
				if(!dev->cmd("AT+CREG=0","OK")){		//检查SIM卡
					//先关闭CREG的额外信息。
					delay_s(2);
					break;
				}
				if(0 == dev->cmd2("AT+CREG?","+CREG: 0,1","+CREG: 0,5", 30))//检查运营商注册
					delay_s(2);
				else
					modify_step(M26_CFG_BOTTOM);
				break;
			case M26_CFG_BOTTOM:		
				if(1 == module_cfg_bottom()){
					modify_step(M26_INIT_OK);
					rec_hadware_status(M26_HARDWARE_OK);
					run_PPPD_srcipt();
					
				}
				else
					delay_s(2);
				break;
				
			default:
				break;
		}
		if(M26_INIT_OK == dev->step)
			return;
        timer_handle();
		delay_ms(100);
	}
}


static void comm_check(void)
{
	if(Timer_Expired_Check_Sq()){		
		get_csq();
//        net4G_do_manage();
//        if(n_lansta.Sta == NET_DOWN) {
//            
//            net4G_do_manage();
//        }
        Timer_Update_Check_Sq();
	}
}

void M26_comm_work(void)
{
	comm_check();
	//get_csq();
}


void M26_servo(void *para, int gaps)
{
    extern  void creat_net_manage(void);
	env_init_step= (*(int*)para)%M26_STPE_MAX;
	M26_dev_init(dev);
    dev->step = env_init_step;
	M26_comm_Init();
	if(gaps > 1000 || gaps < 10){
		gaps= 100;
		m26_dbg("M26 servo run gaps set default val 100\n");
	}
	m26_dbg("M26 env comm init ok\n");
    creat_net_manage();
	while(1)
	{					
		switch(dev->step)
		{
			case M26_INIT_OK:	
				modify_step(M26_GRMS_ESTABLISHED);
				break;		
			case M26_GRMS_ESTABLISHED:	
				M26_comm_work();
				break;
			case M26_PWR_OFF:
			default:
				M26_comm_Init();
				break;
		}	
		delay_ms(gaps);
	}
}


void M26_restart(void)
{
	

}


unsigned char M26_scale_sq(void)
{
/*很弱，弱，中，良好，优秀*/
	unsigned char scale, sq;
	sq= dev->sq;
	if(sq < 12)
		scale= 0;	/*很弱*/
	else if(sq < 18)
		scale= 1;
	else if(sq < 22)
		scale= 2;
	else if(sq < 25)
		scale= 3;
	else
		scale= 4;
	return scale;
}

unsigned char M26_read_sq(void)
{
	return dev->sq;
}

unsigned char cmd_play_tts(unsigned char mode, const unsigned char *buf, unsigned short len)
{
	unsigned char wcnt =3, ret= 0;	
	while(wcnt--)
	{
		dev->cmd("AT+QTTS=0", "OK");/*stop*/
		dev->printf("AT+QTTS=%d,\"",mode);
		dev->send(buf, len);
		if(1 == dev->cmd2("\"\r\n", "OK", "+CME ERROR", 50)){
			ret= 1;
			m26_dbg("tts ok\r\n");
			break;
		}
		else{
			m26_dbg("tts failed\r\n");
			delay_ms(200);
		}
			
	}
	return ret;
}


unsigned char M26_get_sta(void)
{
	return dev->step;
}





